package com.aofeng.hybridwork.android.service;

import android.app.Notification;
import android.app.Service;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import android.os.Message;
import android.os.PowerManager;
import android.support.annotation.Nullable;
import android.util.Log;
import com.aofeng.hybrid.android.receiver.PhoneStatus;
import com.aofeng.hybrid.android.receiver.PhoneStatusReceiver;
import com.aofeng.hybrid.android.service.AbstractService;
import com.aofeng.hybrid.application.AFApplication;
import com.aofeng.hybrid.orm.SqlHelper;
import com.aofeng.hybrid.service.EntityService;
import com.aofeng.hybrid.service.RestService;
import com.aofeng.hybrid.util.CommUtil;
import com.aofeng.hybrid.util.LogUtil;
import com.aofeng.hybridwork.application.HybridApplication;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 系统定时服务，处理地理位置、流量、电量、信号、存储空间状态等
 * Created by LGY on 2016-08-01.
 */
public class TickService extends AbstractService {
    private static final Logger log = LoggerFactory.getLogger(TickService.class);
    private static final int SERVICE_ID = -1001;
    private Player player;
    private boolean shouldStop = false;
    private  Thread theThread;
    PowerManager.WakeLock wakeLock;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    /**
     * 启动工作线程
     * @param alarmInterval
     */
    private void startAThread(final int alarmInterval) {
        theThread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
                    wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                            "alarmLock");
                    wakeLock.acquire();

                    work(alarmInterval);
                } finally {
                    wakeLock.release();
                }
            }
        });
        theThread.start();
        //注册service，供调用
        ((HybridApplication)this.getApplication()).service = this;
    }

    private void work(int alarmInterval) {
        long n = 0;
        Date day = new Date();
        Date preDay = day;
        for(;;) {
            try {
                if(shouldStop) {
                    stopPlayer();
                    return;
                }
                Thread.sleep(alarmInterval);
                n++;
                if((n % HybridApplication.STATUS_COUNTER == 0) && !shouldStop) {
                    checkGpsEnabled();
                    day = new Date();
                    if(day.getDay() != preDay.getDay()) {
                        if(reportDailyStatus(preDay))
                            preDay = day;
                    }
                    reportMinuteStatus(day);
                }
                //response to stop in time
                if(!shouldStop)
                    checkSlips();
                LogUtil.e("cycle " + n, "mission completed");
            } catch (InterruptedException e) {
                e.printStackTrace();
                stopPlayer();
            }

        }
    }

    /**
     * GPS是特殊设备，需要定时去检测是否已经打开
     */
    private void checkGpsEnabled() {
        PhoneStatusReceiver.setupGPSReceiver(this);
    }

    private void stopPlayer() {
        if(player != null) {
            player.stop();
            player = null;
        }
    }

    /**
     * 报告上一天的状态
     */
    private boolean reportDailyStatus(Date yesterday) {
        try {
            String userName = CommUtil.getSharedPreference(this, "f_user_name");
            if(userName.equals(""))
                return false;
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String ymd = sdf.format(yesterday);
            JSONObject jo = PhoneStatus.getDailyPhoneStatus(this, ymd);
            jo.put("f_user_name", userName);
            jo.put("f_user_id", CommUtil.getSharedPreference(this, "f_user_id"));
            sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            jo.put("f_realtime", sdf.format(yesterday));
            sdf = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
            jo.put("f_datetime", sdf.format(yesterday));
            jo.put("f_period", "天");
            jo.put("f_subcompany", CommUtil.getSharedPreference(this, "f_subcompany"));
            //上传日数据
            JSONObject data = new JSONObject();
            data.put("data", jo);
            HttpPost httpPost = new HttpPost(HybridApplication.ENTITY_SERVICE_URL + "t_phone_state");
            httpPost.setEntity(new StringEntity(String.format("%s", data.toString()), "UTF8"));
            HttpClient httpClient = new DefaultHttpClient();
            HttpResponse response = httpClient.execute(httpPost);
            return response.getStatusLine().getStatusCode() == 200;
        } catch (Exception e)
        {
            e.printStackTrace();
            LogUtil.e("安检员状态", "上传天状态数据出错，请检查网络。");
            return false;
        }
    }

    /**
     * 报告实时状态
     */
    private void reportMinuteStatus(Date timestamp) {
        try {
            String userName = CommUtil.getSharedPreference(this, "f_user_name");
            if(userName.equals(""))
                return;
            JSONObject jo = PhoneStatus.getPhoneStatus(this, timestamp);
            if(jo.getString("f_longitude").equals("0.0"))
                jo.put("f_longitude", "0");
            if(jo.getString("f_latitude").equals("0.0"))
                jo.put("f_latitude", "0");
            if(!jo.getString("f_longitude").equals("0")) {
                HttpGet httpGet = new HttpGet("http://api.map.baidu.com/geoconv/v1/?coords=" + jo.get("f_longitude") + "," + jo.get("f_latitude") + "&ak=CAErfbr2DatVA6rHdoUELPynrdPh9A6S&output=json");
                HttpClient httpClient = new DefaultHttpClient();
                HttpResponse response = httpClient.execute(httpGet);
                BufferedReader rd = null;
                try {
                    rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
                    String line = rd.readLine();
                    JSONObject jr = new JSONObject((line));
                    jr = jr.getJSONArray("result").getJSONObject(0);
                    jo.put("f_longitude", jr.getString("x"));
                    jo.put("f_latitude", jr.getString("y"));
                }
                finally {
                    if(rd != null)
                        rd.close();
                }
            }
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            jo.put("f_user_name", userName);
            jo.put("f_user_id", CommUtil.getSharedPreference(this, "f_user_id"));
            jo.put("f_realtime", sdf.format(timestamp));
            sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:00");
            jo.put("f_datetime", sdf.format(timestamp));
            jo.put("f_period", "分");
            jo.put("f_subcompany", CommUtil.getSharedPreference(this, "f_subcompany"));
            //上传分数据
            JSONObject data = new JSONObject();
            data.put("data", jo);
            HttpPost httpPost = new HttpPost(HybridApplication.LOGIC_SERVICE_URL + URLEncoder.encode("上报手机状态", "UTF-8"));
            httpPost.setEntity(new StringEntity(String.format("%s", data.toString()), "UTF8"));
            HttpClient httpClient = new DefaultHttpClient();
            HttpResponse response = httpClient.execute(httpPost);
        } catch (Exception e)
        {
            e.printStackTrace();
            LogUtil.e("安检员状态", "上传实时状态数据出错，请检查网络。");
        }
    }


    /**
     * 检查新通知、新计划等
     */
    private void checkSlips() {
        LogUtil.e("检查新工单", "后台推送中......");
        String role = CommUtil.getSharedPreference(this, "f_user_role");
        boolean hasNew = hasNewNotices();
        if(!role.equals("")) {
            if (role.equals("checker"))
                hasNew |= hasNewPlan();
            if (role.equals("repairman"))
                hasNew |= hasNewRepairs();
        }
        if (hasNew)
            player.play(this, com.aofeng.hybrid.R.raw.ding);
    }

    /**
     * 是否有新维修
     * @return
     */
    private boolean hasNewRepairs() {
        try {
            String lastSuccessFetch = CommUtil.getSharedPreference(this, "Repair_Till");
            RestService rs = new RestService(this);
            JSONObject jo = new JSONObject();
            jo.put("action", "post");
            String sql = "select distinct p from t_check_paper p" +
                    " left join fetch p.f_meters m left join fetch p.f_plumbs pl left join fetch p.f_alarms a left join fetch p.f_inner_plumbs i left join fetch p.f_cookers c left join fetch p.f_valves v left join fetch p.f_furnaces f left join fetch p.f_heaters h left join fetch p.f_defects x " +
                    " where p.f_offsite_time >'" + lastSuccessFetch + "' and p.f_repairman = '" +
                    CommUtil.getSharedPreference(this, "f_user_name") + "' and f_entry_status = '入户' and p.f_defect_urgency is not null and p.f_repaired='未修'" +
                    " and p.f_subcompany='" + CommUtil.getSharedPreference(this, "f_subcompany") + "' and p.f_approved='已审核'";
            jo.put("url", HybridApplication.BASE_URL + "/db/hql");
            jo.put("data", sql);
            JSONArray list = (JSONArray) rs.execute(jo);
            if(list.length() > 0) {
                appendRepairs(list);
                CommUtil.setSharedPreference(this,"f_untreated_repairs", list.length() + "");
                return true;
            } else
                return false;
        } catch(Exception e) {
            return false;
        }
    }

    /**
     * 下载维修单
     * @param list
     * @throws Exception
     */
    private void appendRepairs(JSONArray list) throws Exception {
        String f_time = list.getJSONObject(0).getString("f_offsite_time");
        EntityService es = new EntityService(this);
        for(int i=0; i< list.length(); i++) {
            JSONObject obj = list.getJSONObject(i);
            if(obj.getString("f_offsite_time").compareTo(f_time) > 0)
                f_time = obj.getString("f_offsite_time");
            //删除可能的安检单
            deletePossibleCheckPaper(obj.getString("f_check_item_id"), obj.getString("f_checker_id"));
            //修改图片和录音路径
            Map<String, String> pics = new HashMap<String, String>();
            modifyPicPath(obj, pics);
            //下载图片和录音
            for(String key : pics.keySet()) {
                downloadPic(key, pics.get(key));
            }
            //保存安检单到本地
            es.append("t_check_paper", obj);
        }
        CommUtil.setSharedPreference(this, "Repair_Till", f_time);
    }

    /**
     * 下载图片
     * @param picId
     * @param picFileName
     * @throws Exception
     */
    private void downloadPic(String picId, String picFileName) throws  Exception {
        URL url = new URL(HybridApplication.BASE_URL + "/db/file/" + picId);
        HttpURLConnection conn = (HttpURLConnection)url.openConnection();
        InputStream is = conn.getInputStream();
        FileOutputStream os = new FileOutputStream(picFileName);
        byte[] buf = new byte[1024];

        while(true) {
            int numread = is.read(buf);
            if(numread == -1) {
                is.close();
                os.close();
                return;
            }

            os.write(buf, 0, numread);
        }
    }

    /**
     * 调整图片位置
     * @param paper
     * @throws Exception
     */
    private void modifyPicPath(JSONObject paper, Map<String, String> pics) throws Exception {
        Iterator<String> itr = paper.keys();
        String[] keys = new String[paper.length()];
        int i = 0;
        while (itr.hasNext()) {
            keys[i++] = itr.next();
        }

        for (String key : keys) {
            if (!paper.isNull(key)) {
                if (key.endsWith("_path")) {
                    String value = paper.getString(key);
                    if(value.endsWith("nopic.png")) {
                        paper.put(key, "file:///android_asset/nopic.png");
                    } else {
                        paper.put(key, "file://" + AFApplication.APP_DATA + value);
                        pics.put(value, AFApplication.APP_DATA + value);
                    }
                } else {
                    Object obj = paper.get(key);
                    if (obj instanceof JSONArray) {
                        JSONArray array = (JSONArray) obj;
                        for (i = 0; i < array.length(); i++) {
                            modifyPicPath(array.getJSONObject(i), pics);
                        }
                    }
                }
            }
        }
    }

    /**
     * 删除本地的可能的安检单
     * @param f_check_item_id
     * @Param f_checker_id
     * @throws Exception
     */
    private void deletePossibleCheckPaper(String f_check_item_id, String f_checker_id) throws Exception{
        SqlHelper.run(this, "delete from t_check_paper_meter where f_paper_id in (select id from t_check_paper where f_check_item_id ='" + f_check_item_id + "' and f_checker_id='" + f_checker_id + "')");
        SqlHelper.run(this, "delete from t_check_paper_plumb where f_paper_id in (select id from t_check_paper where f_check_item_id ='" + f_check_item_id + "' and f_checker_id='" + f_checker_id + "')");
        SqlHelper.run(this, "delete from t_check_paper_innerplumb where f_paper_id in (select id from t_check_paper where f_check_item_id ='" + f_check_item_id + "' and f_checker_id='" + f_checker_id + "')");
        SqlHelper.run(this, "delete from t_check_paper_defect where f_paper_id in (select id from t_check_paper where f_check_item_id ='" + f_check_item_id + "' and f_checker_id='" + f_checker_id + "')");
        SqlHelper.run(this, "delete from t_check_paper_alarm where f_paper_id in (select id from t_check_paper where f_check_item_id ='" + f_check_item_id + "' and f_checker_id='" + f_checker_id + "')");
        SqlHelper.run(this, "delete from t_check_paper_cooker where f_paper_id in (select id from t_check_paper where f_check_item_id ='" + f_check_item_id + "' and f_checker_id='" + f_checker_id + "')");
        SqlHelper.run(this, "delete from t_check_paper_valve where f_paper_id in (select id from t_check_paper where f_check_item_id ='" + f_check_item_id + "' and f_checker_id='" + f_checker_id + "')");
        SqlHelper.run(this, "delete from t_check_paper_furnace where f_paper_id in (select id from t_check_paper where f_check_item_id ='" + f_check_item_id + "' and f_checker_id='" + f_checker_id + "')");
        SqlHelper.run(this, "delete from t_check_paper_heater where f_paper_id in (select id from t_check_paper where f_check_item_id ='" + f_check_item_id + "' and f_checker_id='" + f_checker_id + "')");
        SqlHelper.run(this, "delete from t_check_paper where f_check_item_id ='" + f_check_item_id + "' and f_checker_id='" + f_checker_id + "'");
    }

    /**
     * 是否有新计划
     * @return
     */
    private boolean hasNewPlan() {
        try {
            String lastSuccessFetch = CommUtil.getSharedPreference(this, "Plan_Till");
            RestService rs = new RestService(this);
            JSONObject jo = new JSONObject();
            jo.put("action", "post");
            jo.put("url", HybridApplication.SQL_SERVICE_URL + URLEncoder.encode("检查新计划", "UTF-8"));
            jo.put("data", "{\"data\":{\"f_issue_time\":\"" + lastSuccessFetch + "\", \"f_checker_id\":\"" + CommUtil.getSharedPreference(this, "f_user_id") + "\"}}");
            JSONArray list = (JSONArray) rs.execute(jo);
            if(list.length() > 0) {
                appendPlans(list);
                CommUtil.setSharedPreference(this,"f_preset_checks", list.length() + "");
                return true;
            } else
                return false;
        } catch(Exception e) {
            return false;
        }
    }

    /**
     * 添加计划
     * @param list
     * @throws Exception
     */
    private void appendPlans(JSONArray list) throws Exception{
        String f_time = list.getJSONObject(0).getString("f_issue_time");
        EntityService es = new EntityService(this);
        for(int i=0; i< list.length(); i++) {
            JSONObject obj = list.getJSONObject(i);
            if(obj.getString("f_issue_time").compareTo(f_time) > 0)
                f_time = obj.getString("f_issue_time");
            es.append("t_check_plan", obj);
        }
        CommUtil.setSharedPreference(this, "Plan_Till", f_time);
    }

    /**
     * 是否有新通知
     * @return
     */
    private boolean hasNewNotices() {
        try {
            String lastSuccessFetch = CommUtil.getSharedPreference(this, "Notice_Till");
            RestService rs = new RestService(this);
            JSONObject jo = new JSONObject();
            jo.put("action", "post");
            jo.put("url", HybridApplication.SQL_SERVICE_URL + URLEncoder.encode("检查新通知", "UTF-8"));
            jo.put("data", "{\"data\":{\"f_time\":\"" + lastSuccessFetch + "\"}}");
            JSONArray list = (JSONArray) rs.execute(jo);
            if(list.length() > 0) {
                appendNotices(list);
                CommUtil.setSharedPreference(this,"f_unread_notices", list.length() + "");
                return true;
            } else
                return false;
        } catch(Exception e) {
            return false;
        }
    }

    /**
     * 添加通知到数据库
     * @param list
     */
    private void appendNotices(JSONArray list) throws Exception {
        String f_time = list.getJSONObject(0).getString("f_time");
        EntityService es = new EntityService(this);
        for(int i=0; i< list.length(); i++) {
            JSONObject obj = list.getJSONObject(i);
            obj.remove("id");
            if(obj.getString("f_time").compareTo(f_time) > 0)
                f_time = obj.getString("f_time");
            es.save("t_notice", obj);
        }
        CommUtil.setSharedPreference(this, "Notice_Till", f_time);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e("MyService", "Received start id " + startId + ": " + intent);
        if (Build.VERSION.SDK_INT < 18) {
            startForeground(SERVICE_ID, new Notification());//API < 18 ，此方法能有效隐藏Notification上的图标
        } else {
            Intent innerIntent = new Intent(this, TickShadowService.class);
            startService(innerIntent);
            startForeground(SERVICE_ID, new Notification());
        }
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onStartService() {
        LogUtil.e("新建service对象", "创建服务对象并启动服务");
        player = new Player();
        initNotifications();
        startAThread(HybridApplication.BASE_INTERVAL);
    }

    /**
     * 初始化动态推送，通知只推送一次
     */
    private void initNotifications() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String stamp = sdf.format(new Date());
        if(CommUtil.getSharedPreference(this, "Notice_Till").equals("")) {
            CommUtil.setSharedPreference(this, "Notice_Till", stamp);
            CommUtil.setSharedPreference(this, "Plan_Till", stamp);
            CommUtil.setSharedPreference(this, "Repair_Till", "1980-01-01");
        }
    }

    @Override
    public void onStopService() {
        stopPlayer();
        shouldStop = true;
        ((HybridApplication)this.getApplication()).service = null;
    }

    /**
     * 播放器静音
     */
    public void mute()
    {
        player.stop();
        CommUtil.setSharedPreference(this, "f_unread_notices", "0");
        CommUtil.setSharedPreference(this, "f_preset_checks", "0");
        CommUtil.setSharedPreference(this, "f_untreated_repairs", "0");
    }

    @Override
    public void onReceiveMessage(Message msg) {

    }

    /**
     * 给 API >= 18 的平台上用的灰色保活手段
     */
    public static class TickShadowService extends Service {

        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            startForeground(SERVICE_ID, new Notification());
            stopForeground(true);
            stopSelf();
            return super.onStartCommand(intent, flags, startId);
        }

        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }

    }
}
